package cli.menu;


import java.util.Date;
import java.util.SortedSet;
import shared.*;

public class GeneralReport extends Function{
	
	private static String[] select = {
		"-= Main menu > General Report =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Please selet a time frame",
		"1. Today",
		"2. This Month",
		"3. This Year",
		"",
		"Please enter your option: "
	};
	
	private static State back = State.MAINMENU;
	private static State current = State.GENERALREPORT;
	
	public static State runMenu(){
		
		cli.print(select);
		
	
		String input = cli.nextLine();
	
		
		return processInput(input);
	}
	
	private static State processInput(String input){
		State nextState = current;
		if(input.length()!=1)
			return current;
		else{
			char charInput = input.charAt(0);
			switch (charInput) {
			case '1':
				nextState = printGeneralReport(1, "day");
				break;
			case '2':
				nextState =  printGeneralReport(1, "month");
				break;
			case '3':
				nextState =  printGeneralReport(1, "year");
				break;
			case 'u':
			case 'U':
				tools.undo();
				break;
			case 'r':
			case 'R':
				tools.redo();
				break;
			case 'b':
			case 'B':
				nextState = back;
				break;
			case 'H':
			case 'h':
				nextState = State.MAINMENU;
			default:
				cli.print(INVALIDINPUT);
			}
		}
		return nextState;
	}
	
	public static State printGeneralReport(int requestPage, String option) {
		int currentPage = requestPage;
		int[] today = new int[3];
		today = tools.initDate();
		int day = today[0];
		int month = today[1];
		int year = today[2];
		Date currentDate = new Date();
		String date = tools.formatDate(currentDate);
		SortedSet<Record> record = null;

		if (option.equals("day")) {
			record = cli.getApi().getDateRange(day, month, year, day + 1, month, year);
		} else if (option.equals("month")) {
			record = cli.getApi().getDateRange(1, month, year, day + 1, month, year);
		} else if (option.equals("year")) {
			record = cli.getApi().getDateRange(1, 1, year, day + 1, month, year);
		} else {
			cli.print(INVALIDINPUT);
			return current;
		}

		Object[] recordArr = record.toArray();

		// calculate total expense, income, owed, balance
		int expense = 0;
		int income = 0;
		int owed = 0;
		int balance = 0;

		for (Object r : recordArr) {
			if (r.getClass() == Expense.class) {
				expense += ((Record) r).getAmt();
			} else if (r.getClass() == Income.class) {
				income += ((Record) r).getAmt();
			} else if (r.getClass() == Loan.class) {
				owed += ((Loan) r).getOutstanding();
			}
		}
		balance = income - expense;

		double totalExpense = (double) expense / 100.00;
		double totalIncome = (double) income / 100.00;
		double totalOutstanding = (double) owed / 100.00;
		double totalBalance = (double) balance / 100.00;
		// ==================== Print Page===================================
		// ---------------- Header -----------------------------------

		/*
		cli.println("-= Main menu > General Report > This Year =-");
		cli.println("[b]: back [u]: undo [r]: redo [h]: home menu");
		cli.println("");
		if (option.equalsIgnoreCase("day")) {
			cli.println("For the Day " + date);
		} else if (option.equalsIgnoreCase("month")) {
			cli.println("For the Month " + month + "." + year);
		} else if (option.equalsIgnoreCase("year")) {
			cli.println("For the Year " + year);
		} else {
			throw new Exception("track expense request option is not available");
		}
	*/

		while (true) {
			cli.println("-= Main menu > General Report > This Year =-");
			cli.println("[b]: back [u]: undo [r]: redo [h]: home menu");
			cli.println("");
			if (option.equalsIgnoreCase("day")) {
				cli.println("For the Day " + date);
			} else if (option.equalsIgnoreCase("month")) {
				cli.println("For the Month " + month + "." + year);
			} else if (option.equalsIgnoreCase("year")) {
				cli.println("For the Year " + year);
			} else {
				cli.print(INVALIDINPUT);
				return current;
			}

			cli.printf("Total Expenses: $%.2f\n", totalExpense);
			cli.printf("Total Income:   $%.2f\n", totalIncome);
			cli.printf("Total Owed:     $%.2f\n", totalOutstanding);
			cli.printf("Balance:        $%.2f\n", totalBalance);
			cli.println("");
			// ---------------- end of Header -------------------------------

			// set report body format
			int DATE_LEN = 10;
			int NAME_LEN = 20;
			int AMT_LEN = 10;
			int MODE_LEN = 10;
			int CAT_LEN = 20;
			int ENTRY_PER_PAGE = 15;
			int tableWidth = 2 + DATE_LEN + 3 + NAME_LEN + 3 + 2 * AMT_LEN + 6
					+ MODE_LEN + 3 + CAT_LEN + 2;

			// report variable
			int lastPage = (record.size() % ENTRY_PER_PAGE == 0) ? (record
					.size() / ENTRY_PER_PAGE)
					: (record.size() / ENTRY_PER_PAGE + 1);
			Record rec;
			Expense ex;
			int lastEntry;

			// constant string to print
			String lineDiv = tools.printLine("-", tableWidth);

			// -----------------print title ------------------------------
			cli.println(lineDiv);

			cli.print("| " + tools.formatString("Date", DATE_LEN) + " ");
			cli.print("| " + tools.formatString("Name", NAME_LEN) + " ");
			cli.print("| " + tools.formatString("Amount", AMT_LEN * 2)
					+ "    ");
			cli.print("| " + tools.formatString("Mode", MODE_LEN) + " ");
			cli.print("| " + tools.formatString("Category", CAT_LEN) + " ");
			cli.println("|");

			cli.println(lineDiv);

			cli.print("|||||||||||||");
			cli.print("|||");
			for (int k = 0; k < NAME_LEN; k++) {
				cli.print("|");
			}
			cli.print("| " + tools.formatString("Incoming", AMT_LEN) + " ");
			cli.print("| " + tools.formatString("Outgoing", AMT_LEN) + " ");
			cli.print("|||");
			for (int k = 0; k < MODE_LEN; k++) {
				cli.print("|");
			}
			cli.print("|||");
			for (int k = 0; k < CAT_LEN; k++) {
				cli.print("|");
			}
			cli.println("|");

			cli.println(lineDiv);
			// ----------------------end of title -----------------------------

			// ----------------------print entries -----------------------------
			if (lastPage == 0) {
				cli.println("No entry found for the period");
			} else {
				// prevent overflow
				if (currentPage <= 0) {
					currentPage = 1;
				}
				if (currentPage > lastPage) {
					currentPage = lastPage;
				}

				if (currentPage == lastPage) {
					lastEntry = record.size();
				} else {
					lastEntry = currentPage * ENTRY_PER_PAGE;
				}

				for (int i = (currentPage - 1) * ENTRY_PER_PAGE; i < lastEntry; i++) {
					if (!(recordArr[i] instanceof Record)) {
						cli.print(ERROR);
						return current;
					}

					if (recordArr[i] instanceof Expense) {
						ex = (Expense) recordArr[i];
						cli
								.print("| "
										+ tools.formatString(
												ex.getDay() + "/"
														+ ex.getMonth() + "/"
														+ ex.getYear(),
												DATE_LEN) + " ");
						cli.print("| "
								+ tools.formatString(ex.getName(), NAME_LEN) + " ");
						cli.print("| " + tools.formatString("-", AMT_LEN)
								+ " ");
						cli.printf("| $%9.2f ",
								(double) ex.getAmt() / 100.0);
						cli
								.print("| "
										+ tools.formatString(ex.getMode().getName(),
												MODE_LEN) + " ");
						cli.print("| "
								+ tools.formatString(ex.getCat().getName(), CAT_LEN)
								+ " ");
						cli.println("|");
						cli.println(lineDiv);
					} else {
						rec = (Record) recordArr[i];
						cli
								.print("| "
										+ tools.formatString(
												rec.getDay() + "/"
														+ rec.getMonth() + "/"
														+ rec.getYear(),
												DATE_LEN) + " ");
						cli.print("| "
								+ tools.formatString(rec.getName(), NAME_LEN) + " ");
						cli.printf("| $%9.2f ",
								(double) rec.getAmt() / 100.0);
						cli.print("| " + tools.formatString("-", AMT_LEN)
								+ " ");
						cli.print("| " + tools.formatString("-", MODE_LEN)
								+ " ");
						cli.print("| " + tools.formatString("-", CAT_LEN)
								+ " ");
						cli.println("|");
						cli.println(lineDiv);
					}
				}
			}
			// ------------ end of entries
			// -------------------------------------------

			// -------------print footer
			// ---------------------------------------------
			if (lastPage > 1) {
				String ppg = "|<[P: previous]";
				String cp = "Page[" + currentPage;
				String lp = "/" + lastPage + "]";
				String npg = "[N: next]>|";
				int space = tableWidth - ppg.length() - cp.length()
						- lp.length() - npg.length();
				if (space < 0)
					space = 0;
				int halfSpace1 = space / 2;
				int halfSpace2 = space - halfSpace1;

				cli.print(ppg);
				for (int k = 0; k < halfSpace1; k++) {
					cli.print(" ");
				}
				cli.print(cp);
				cli.print(lp);
				for (int k = 0; k < halfSpace2; k++) {
					cli.print(" ");
				}
				cli.print(npg);
				cli.println();

				cli.println(lineDiv);
			}
			// ------------end of footer
			// --------------------------------------------

			// ==================== end of print report
			// =========================

			// read input
	
			String input = cli.nextLine();
			
			if(input == null || input.length() != 1)
				return back;

			char charInput = input.charAt(0);

			switch (charInput) {
			case 'p':
			case 'P':
				currentPage--;
				break;
			case 'n':
			case 'N':
				currentPage++;
				break;
			case 'b':
			case 'B':
				return back;
			case 'u':
			case 'U':
				tools.undo();
				break;
			case 'r':
			case 'R':
				tools.redo();
				break;
			case 'h':
			case 'H':
				return State.MAINMENU;
			default:
			cli.print(INVALIDINPUT);
			break;
			}
		}
	}
	
}